﻿using LoongCAD.Geometry;
using LoongCAD.Geometry.Friendly;
using LoongCAD.STC;
using LoongCAD.STC.Friendly.Plugins;
using LoongCAD.STC.Friendly.Scene;
using LoongCAD.STC.Friendly.Scene.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CustonDemo
{
    //============组件通用属性=============
    [Plugin("CustomDemo")]                              //组件名称
    [PluginUserInterface("Form_PluginMain")]            //指定窗口类名称 
    [PluginNumber(9999)]                                //组件编号
    public class CustomDemo : CustomPlugin
    {
        //当前创建的组件实例
        Component comp;
        //组件窗口传入参数
        public StructuresData data;
        //用户输入参数
        List<Point> inputPoints;

        //自己建立的坐标系
        Matrix refMat;

        //=======创建过程相关的参数=========

        double beamLength = 0.0;

        Part web;
        public CustomDemo(StructuresData data)
        { 
            this.data = data;
        }

        /// <summary>
        /// 自定义用户场景输入参数
        /// （自定义组件必须实现此方法）
        /// </summary>
        /// <returns></returns>
        public override List<InputDefinition> DefineInput()
        {
            try
            {
                //使用用户交互选择器捕捉需要的场景参数
                Picker picker = new Picker();
                //需要两个点所以使用PickPoints()函数来决定输入点，需要其他类型的参数则调用其对应的Pick方法，详情参考SDK
                List<Point> points = picker.PickPoints(Picker.PickPointEnum.PICK_TWO_POINTS, "选择两个点");
                List<InputDefinition> input = new List<InputDefinition>();
                if(points.Count < 2)return input;
                input.Add(new InputDefinition(points));
                return input;
            }
            catch (UserInterruptException e)
            {
                return null;
            }
        }

        public override bool Run(Component componentObject, List<InputDefinition> input)
        {
            comp = componentObject;
            //输入合法性检查
            if(input == null || input.Count == 0)return false;
            inputPoints = input[0].GetInput() as List<Point>;

            //计算参数
            CalcParams();
            //设置当前工作平面，之后的所有的几何数据(点，向量等)都会以这个工作平面为基准
            comp.Scene.SetCurrentTransformationPlane(new TransformationPlane(refMat));
            //创建腹板
            CreateWeb();
            //创建翼缘
            CreateFlg();
            //将当前工作平面还原
            refMat.Inverse();
            comp.Scene.SetCurrentTransformationPlane(new TransformationPlane(refMat));
            return true;
        }

        void CalcParams()
        {
            //计算参考坐标系
            { 
                Point startPoint = inputPoints[0];
                Point endPoint = inputPoints[1];
                beamLength = startPoint.Dist(endPoint);

                Point origin = startPoint;
                Vector aixsX = endPoint - startPoint;
                aixsX.Normalize();

                Vector aixsY = Vector.AXIS_Z.Cross(aixsX);
                if (aixsY.IsParallelTo(Vector.AXIS_Z)) aixsY = Vector.AXIS_Y;

                Vector aixsZ = aixsX.Cross(aixsY);

                refMat = new Matrix(origin, aixsX, aixsY, aixsZ);

#if DEBUG
                CreateAssistCoord(aixsX, aixsY, aixsZ, origin);
#endif
            }

        }


        //绘制创建的坐标系
        void CreateAssistCoord(Vector dirX, Vector dirY, Vector dirZ, Point p0, double len = 1000)
        {
            //O
            ControlPoint cp = new ControlPoint();
            cp.Point = new Point(p0);
            cp.Insert();

            //X
            ControlLine x = new ControlLine();
            x.Line = new LineSegment(new Point(p0), new Point(p0 + dirX * len));
            x.Color = new Color(1.0, 0.0, 0.0);
            x.Extension = 100;
            x.Insert();
            //y
            ControlLine y = new ControlLine();
            y.Line = new LineSegment(new Point(p0), new Point(p0 + dirY * len));
            y.Color = new Color(0.0, 1.0, 0.0);
            y.Extension = 100;
            y.Insert();
            //z
            ControlLine z = new ControlLine();
            z.Line = new LineSegment(new Point(p0), new Point(p0 + dirZ * len));
            z.Color = new Color(0.0, 0.0, 1.0);
            z.Extension = 100;
            z.Insert();
        }


        void CreateWeb()
        {
            Point p1 = Point.ZERO;
            Point p2 = p1 + Vector.AXIS_X * beamLength;
            double thickness = data.webProps.Thickness;
            double width = data.webProps.Width;
            //=======创建梁并设置属性========
            Beam beam = new Beam();
            //梁的控制点(会随工作平面变化而变化)
            //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
            beam.StartPoint = p1;
            beam.EndPoint = p2;
            //梁的空间位置属性(会随工作平面变化而变化）
            //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
            beam.Position.Depth = Position.DepthEnum.MIDDLE;
            beam.Position.DepthOffset = 0;
            beam.Position.Rotation = Position.RotationEnum.TOP;
            beam.Position.RotationOffset = 0;
            beam.Position.Plane = Position.PlaneEnum.MIDDLE;
            beam.Position.PlaneOffset = 0;
            //梁的业务逻辑属性
            beam.Profile.ProfileString = "PL" + thickness + "*" + width;
            beam.PartNumber.Prefix = data.webProps.NoPrefix;
            beam.Name = data.webProps.Name;
            beam.Material.MaterialString = data.webProps.Material;
            beam.Class = "7";
            //向程序发送创建指令
            beam.Insert();

            web = beam;
        }

        void CreateFlg()
        {
            double thickness = data.flgProps.Thickness;
            double width = data.flgProps.Width;
            double webWidth = data.webProps.Width;

            {
                Point p1 = new Point(0, 0, webWidth / 2 + thickness / 2);
                Point p2 = p1 + Vector.AXIS_X * beamLength;

                //=======创建梁并设置属性========
                Beam beam = new Beam();
                //梁的控制点(会随工作平面变化而变化)
                //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
                beam.StartPoint = p1;
                beam.EndPoint = p2;
                //梁的空间位置属性(会随工作平面变化而变化）
                //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
                beam.Position.Depth = Position.DepthEnum.MIDDLE;
                beam.Position.DepthOffset = 0;
                beam.Position.Rotation = Position.RotationEnum.FRONT;
                beam.Position.RotationOffset = 0;
                beam.Position.Plane = Position.PlaneEnum.MIDDLE;
                beam.Position.PlaneOffset = 0;
                //梁的业务逻辑属性
                beam.Profile.ProfileString = "PL" + thickness + "*" + width;
                beam.PartNumber.Prefix = data.flgProps.NoPrefix;
                beam.Name = data.flgProps.Name;
                beam.Material.MaterialString = data.flgProps.Material;
                beam.Class = "7";
                //向程序发送创建指令
                beam.Insert();

                if (data.weldIsCreate == 1) CreateWeld(web, beam);
            }

            {
                Point p1 = new Point(0, 0,-(webWidth / 2 + thickness / 2));
                Point p2 = p1 + Vector.AXIS_X * beamLength;
                //=======创建梁并设置属性========
                Beam beam = new Beam();
                //梁的控制点(会随工作平面变化而变化)
                //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
                beam.StartPoint = p1;
                beam.EndPoint = p2;
                //梁的空间位置属性(会随工作平面变化而变化）
                //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
                beam.Position.Depth = Position.DepthEnum.MIDDLE;
                beam.Position.DepthOffset = 0;
                beam.Position.Rotation = Position.RotationEnum.FRONT;
                beam.Position.RotationOffset = 0;
                beam.Position.Plane = Position.PlaneEnum.MIDDLE;
                beam.Position.PlaneOffset = 0;
                //梁的业务逻辑属性
                beam.Profile.ProfileString = "PL" + thickness + "*" + width;
                beam.PartNumber.Prefix = data.flgProps.NoPrefix;
                beam.Name = data.flgProps.Name;
                beam.Material.MaterialString = data.flgProps.Material;
                beam.Class = "7";
                //向程序发送创建指令
                beam.Insert();

                if (data.weldIsCreate == 1) CreateWeld(web, beam);
            }
        }

        /// <summary>
        /// 创建焊缝
        /// </summary>
        /// <param name="mainPart">主零件</param>
        /// <param name="subPart">次零件</param>
        /// <param name="pos">自动探测方向</param>
        void CreateWeld(Part mainPart, Part subPart, Weld.WeldPositionEnum pos = BaseWeld.WeldPositionEnum.WELD_POSITION_PLUS_X)
        {
            Weld w = new Weld();
            //指定主次零件
            w.MainObject = mainPart;
            w.SecondaryObject = subPart;
            //指定自动探测方向
            w.Position = pos;
            //如果有需要可添加焊缝的业务逻辑属性

            //向程序发送创建指令
            w.Insert();
        }
    }
}
